package com.pansoft.openplanet.activity.child;

import android.content.DialogInterface;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.core.xml.StubObject;
import com.efounder.frame.baseui.BaseFragment;
import com.efounder.http.EFHttpRequest;
import com.efounder.util.AppContext;
import com.efounder.util.ToastUtil;
import com.efounder.utils.ResStringUtil;
import com.pansoft.openplanet.R;
import com.pansoft.openplanet.account.util.EosAccountGenerator;
import com.pansoft.openplanet.bean.Account;
import com.pansoft.openplanet.bean.WalletBean;
import com.pansoft.openplanet.blockchain.api.EosChainInfo;
import com.pansoft.openplanet.blockchain.chain.SignedTransaction;
import com.pansoft.openplanet.blockchain.types.TypeChainId;
import com.pansoft.openplanet.db.AccountDao;
import com.pansoft.openplanet.fragment.BottomWalletChooseDialogFragment;
import com.pansoft.openplanet.util.EosNetParamUtil;
import com.pansoft.openplanet.util.TCMathUtil;
import com.pansoft.openplanet.util.TCRequestUtil;
import com.pansoft.openplanet.widget.TCLoadingDataView;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.listener.OnRefreshListener;
import com.utilcode.util.JFStringUtil;
import com.utilcode.util.ToastUtils;

import org.json.JSONObject;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

import static android.app.DialogFragment.STYLE_NO_FRAME;

/**
 * 帮助好友创建eos账户界面
 *
 * @author wwl
 */
public class
HelpCreateEosFragment extends BaseFragment implements View.OnClickListener {

    public static final String TAG = "HelpCreateEosFragment";
    private TextView tvFee;
    private TextView tvFeeValue;
    private TextView tvRam;
    private TextView tvRamValue;
    private TextView tvCpu;
    private TextView tvCpuValue;
    private TextView tvNet;
    private TextView tvNetValue;
    private EditText etAccountName;
    private TextView tvNameCheck;
    private TextView tvOwnerKey;
    private TextView tvActiveKey;
    private Button tvCreateWallet;
    private LinearLayout llAddress;
    private TextView tvWallet;
    private LinearLayout llAccount;
    private TextView tvAccount;
    private SmartRefreshLayout srlRefresh;

    private StubObject stubObject;
    private Hashtable<String, Object> hashtable;
    private String accountName = "";
    private String currentAccountName;//当前选择的付款账户名
    private String ownerPubKey;
    private String activePubKey;
    private boolean clickable = false;
    private Disposable disposable;
    private AccountDao accountDao;
    private Account currentAccount;
    private String[] items;
    private List<WalletBean> walletBeans = new ArrayList<>();
    private String ram, net, cpu;

    public HelpCreateEosFragment() {

    }

    public HelpCreateEosFragment(StubObject stubObject) {
        Hashtable<String, String> hashtable = stubObject.getStubTable();
        Bundle bundle = new Bundle();
        bundle.putSerializable("stubObject", stubObject);
        setArguments(bundle);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.open_planet_activity_confirm_eos_wallet, container, false);
        stubObject = (StubObject) getArguments().getSerializable("stubObject");
        // userId = (String) stubObject.getStubTable().get("toUserId");
        //chatType = (String) stubObject.getStubTable().get("chatType");
        if (stubObject != null) {
            hashtable = stubObject.getStubTable();
        }

        initView(rootView);

        TextView tvTitle = rootView.findViewById(R.id.tv_title);
        tvTitle.setText("创建EOS账户");
        String titles = null;
        if (hashtable != null && hashtable.containsKey("systemName")) {
            titles = (String) hashtable.get("systemName");
            tvTitle.setText(titles);
        }
        initData();
        return rootView;
    }

    private void initView(View rootview) {

        tvFee = rootview.findViewById(R.id.tv_fee);
        tvFeeValue = rootview.findViewById(R.id.tv_fee_value);
        tvRam = rootview.findViewById(R.id.tv_ram);
        tvRamValue = rootview.findViewById(R.id.tv_ram_value);
        tvCpu = rootview.findViewById(R.id.tv_cpu);
        tvCpuValue = rootview.findViewById(R.id.tv_cpu_value);
        tvNet = rootview.findViewById(R.id.tv_net);
        tvNetValue = rootview.findViewById(R.id.tv_net_value);
        etAccountName = rootview.findViewById(R.id.et_account_name);
        tvNameCheck = rootview.findViewById(R.id.tv_name_check);
        tvOwnerKey = rootview.findViewById(R.id.tv_owner_key);
        tvActiveKey = rootview.findViewById(R.id.tv_active_key);
        tvCreateWallet = rootview.findViewById(R.id.tv_create_wallet);
        tvCreateWallet.setOnClickListener(this);
        srlRefresh = rootview.findViewById(R.id.srl_refresh);

        llAddress = rootview.findViewById(R.id.ll_address);
        llAddress.setOnClickListener(this);
        tvWallet = rootview.findViewById(R.id.tv_wallet);
        llAccount = rootview.findViewById(R.id.ll_account);
        llAccount.setOnClickListener(this);
        tvAccount = rootview.findViewById(R.id.tv_account);

        etAccountName.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                accountName = etAccountName.getText().toString();
                if (JFStringUtil.isEosName(accountName)) {

                    verifyAccount();
                } else {
                    tvNameCheck.setVisibility(View.VISIBLE);
                    clickable = false;
                }
            }
        });

        srlRefresh.setOnRefreshListener(new OnRefreshListener() {
            @Override
            public void onRefresh(@NonNull RefreshLayout refreshLayout) {
                initData();
            }
        });
    }

    private void initData() {

        TCLoadingDataView.show(getActivity(), ResStringUtil.getString(R.string.common_text_loading));
        if (hashtable != null) {
            activePubKey = (String) hashtable.get("eosActivePublicKey");
            ownerPubKey = (String) hashtable.get("eosOwnerPublicKey");
            accountName = (String) hashtable.get("eosAccountName");
        } else {
            Bundle bundle = getActivity().getIntent().getExtras();
            activePubKey = (String) bundle.get("eosActivePublicKey");
            ownerPubKey = (String) bundle.get("eosOwnerPublicKey");
            accountName = (String) bundle.get("eosAccountName");
        }
        tvActiveKey.setText(activePubKey);
        tvOwnerKey.setText(ownerPubKey);
        etAccountName.setText(accountName);

        //获取当前EOS价格
        getEosData();

        accountDao = new AccountDao(getActivity());
        currentAccount = accountDao.getCurrentShowAccount(EosNetParamUtil.getEosChainEnum());
//        if (currentAccount == null)
//            return;
        initLocalWalletData();
    }

    /**
     * 初始化本地钱包数据
     */
    private void initLocalWalletData() {
        List<Account> accountList = accountDao.getAllActivatedEosAccount(EosNetParamUtil.getEosChainEnum());
        if (accountList != null) {
            for (int i = 0; i < accountList.size(); i++) {
                Account account = accountList.get(i);
                if (account.getAccountType() == Account.ACCOUNT_TYPE_OBSERVE) {
                    //观察钱包不能转账
                    continue;
                }
                WalletBean walletBean = new WalletBean.Builder()
                        .accountName(account.getAcccountName())
                        .avatar(account.getAccountAvatar())
                        .address(account.getAddress())
                        .balance("0")
                        .build();
                walletBeans.add(walletBean);
            }
        }
        //当前钱包未被激活，遍历所有钱包,取第一个
        if (currentAccount == null || (currentAccount != null && !currentAccount.isActivate())) {
            for (Account account : accountList) {
                if (account.isActivate()) {
                    currentAccount = account;
                    break;
                }
            }
        }
        //钱包下的主账户名
        if (currentAccount != null) {
            currentAccountName = currentAccount.getAddress();
            tvAccount.setText(currentAccountName);
            //钱包名
            tvWallet.setText(currentAccount.getAcccountName());
        }
    }

    private void getEosData() {
        TCRequestUtil.getCommonRequest(TAG, "eos/getEosData", new HashMap<String, String>(), new TCRequestUtil.TCRequestCallback() {
            @Override
            public void onSuccess(String response) {
                try {
                    TCLoadingDataView.dismiss();
                    srlRefresh.finishRefresh();
                    JSONObject jsonObject = new JSONObject(response);
                    if (jsonObject.optString("result").equals("success")) {
                        JSONObject dataObject = jsonObject.optJSONObject("data");
                        Double ramPrice = Double.valueOf(dataObject.optString("ram"));
                        Double netPrice = Double.valueOf(dataObject.optString("net"));
                        Double cpuPrice = Double.valueOf(dataObject.optString("cpu"));

                        Double ramValue = TCMathUtil.mul(ramPrice, 4);
                        Double netValue = TCMathUtil.mul(netPrice, 1);
                        Double cpuValue = TCMathUtil.div(0.3, cpuPrice, 2);
                        Double totalValue = TCMathUtil.add(TCMathUtil.add(ramValue, netValue), 0.3);
                        DecimalFormat df = new DecimalFormat("0.0000");
                        ram = df.format(ramValue) + " EOS";
                        cpu = df.format(cpuValue) + " ms";
                        net = df.format(netValue) + " EOS";

                        tvRamValue.setText(ram);
                        tvCpu.setText(cpu);
                        tvNetValue.setText(net);
                        tvFeeValue.setText(TCMathUtil.bigFormat(totalValue, 4) + " EOS");
                    } else {
                        ToastUtils.showShort(R.string.open_planet_eos_create_params_request_fail);
                    }
                } catch (Exception e) {
                    TCLoadingDataView.dismiss();
                    srlRefresh.finishRefresh();
                    e.printStackTrace();
                    ToastUtils.showShort(R.string.open_planet_eos_create_params_request_fail);
                }
            }

            @Override
            public void onFail(String error) {
                TCLoadingDataView.dismiss();
                srlRefresh.finishRefresh();
                ToastUtils.showShort(R.string.open_planet_eos_create_params_request_fail);
            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
        EFHttpRequest.cancelRequest(TAG);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.tv_create_wallet) {
            if (clickable) {
                createAccount();
            } else {
                ToastUtils.showShort(getString(R.string.account_name_check_hint));
            }

        } else if (id == R.id.ll_address) {
            //切换钱包
            showWalletChoose();
        } else if (id == R.id.ll_account) {
            //切换账户
            if (currentAccount != null) {
                changeAccountAlert();
            }
        }
    }

    /**
     * 验证账户是否存在
     */
    private void verifyAccount() {
        disposable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                EosAccountGenerator eosAccountGenerator = new EosAccountGenerator(getActivity());
                String result = eosAccountGenerator.verifyAccount(TAG, accountName);
                emitter.onNext(result);
                emitter.onComplete();
            }
        }).subscribeOn(Schedulers.io())
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(Disposable disposable) throws Exception {
                        TCLoadingDataView.show(getActivity(), ResStringUtil
                            .getString(R.string.open_planet_checking_account_name));
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        TCLoadingDataView.dismiss();
                        if (s != null && s.equals("success")) {
                            tvNameCheck.setVisibility(View.GONE);
                            clickable = true;
                        } else {
                            ToastUtils.showShort(R.string.open_planet_eos_account_exist);
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        TCLoadingDataView.dismiss();
                    }
                });

    }

    /**
     * 创建钱包，用rxjava
     */
    private void createAccount() {
        if (currentAccount == null) {
            ToastUtils.showShort(getString(R.string.local_eos_wallet_check));
            return;
        }
        disposable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                EosAccountGenerator eosAccountGenerator = new EosAccountGenerator(getActivity());
                //获取链上的信息
                EosChainInfo eosChainInfo = eosAccountGenerator.getChainInfo(TAG);
                //组织数据，得到transaction tx
                //测试
//                SignedTransaction tx = eosAccountGenerator.parseNewAccountData(currentAccountName,
//                        accountName, ownerPubKey, activePubKey, net.replace("EOS", "SYS"),
//                        cpu.replace("EOS", "SYS"), eosChainInfo);
                //正式
                SignedTransaction tx = eosAccountGenerator.parseNewAccountData(currentAccountName,
                        accountName, ownerPubKey, activePubKey, net, cpu, eosChainInfo);
                //对tx签名，返回tx的toString json格式
                String packedTx = eosAccountGenerator.signTransaction(currentAccountName, tx,
                        new TypeChainId(eosChainInfo.getChain_id()));
                //push transaction, 返回交易id
                String txId = eosAccountGenerator.pushTransaction(TAG, packedTx);
                emitter.onNext(txId);
                emitter.onComplete();
            }
        }).subscribeOn(Schedulers.io())
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(Disposable disposable) throws Exception {
                        TCLoadingDataView.show(getActivity(), ResStringUtil.getString(R.string.open_planet_iscreateing));
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        TCLoadingDataView.dismiss();
                        if (s != null) {
                            new android.app.AlertDialog.Builder(getContext())
                                    .setMessage(ResStringUtil.getString(R.string.open_planet_account_create_success))
                                    .setPositiveButton(R.string.common_text_confirm, null).show();
                        } else {
                            ToastUtils.showShort(R.string.open_planet_create_wallet_fail);
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        TCLoadingDataView.dismiss();
                        ToastUtils.showShort(R.string.open_planet_create_wallet_fail);
                    }
                });

//                EosAccountGenerator.getTx(TAG, "eosiotest", etAccountName.getText().toString(),
//                        ownerPubKey, activePubKey);
    }

    /**
     * 切换钱包
     */
    private void showWalletChoose() {
        if (walletBeans != null && walletBeans.size() == 0) {
            ToastUtil.showToast(AppContext.getInstance(), getString(R.string.local_eos_wallet_check));
            return;
        }

        BottomWalletChooseDialogFragment bottomWalletChooseDialogFragment = new
                BottomWalletChooseDialogFragment();
        bottomWalletChooseDialogFragment.setData(getActivity(), walletBeans, EosNetParamUtil.getEosChainId());
        bottomWalletChooseDialogFragment.hideBalace(true);
        bottomWalletChooseDialogFragment.setStyle(STYLE_NO_FRAME, 0);
        bottomWalletChooseDialogFragment.show(getFragmentManager(), "WalletChoose");
        bottomWalletChooseDialogFragment.setOnWalletSelectChangedListener(new BottomWalletChooseDialogFragment.OnWalletSelectChangedListener() {
            @Override
            public void onWalletChanged(WalletBean walletBean) {
                String address = walletBean.getAddress();
                currentAccount = accountDao.getAccount(address);
                currentAccountName = currentAccount.getAddress();
                tvWallet.setText(currentAccount.getAcccountName());
                tvAccount.setText(currentAccountName);
            }
        });
    }

    /**
     * 选择账户
     */
    private void changeAccountAlert() {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        int checkedItem = 0;
        if (currentAccount.getEosAccountNames() == null || currentAccount.getEosAccountNames().equals("")) {
            items = new String[]{currentAccount.getAddress()};
        } else {
            items = currentAccount.getEosAccountNames().split("_");

            for (int i = 0; i < items.length; i++) {
                if (currentAccount.getAddress().equals(items[i])) {
                    checkedItem = i;
                }
            }
        }

        builder
                .setTitle(ResStringUtil.getString(R.string.open_planet_choose_account))
                .setSingleChoiceItems(items, checkedItem, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        currentAccountName = items[i];
                        tvAccount.setText(currentAccountName);
                        dialogInterface.dismiss();
                    }
                })
                .setNegativeButton(R.string.common_text_cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        dialogInterface.dismiss();
                    }
                })
                .setCancelable(false);
        AlertDialog dialog = builder.create();
        dialog.show();
    }
}
